home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / misc / gs261src.zip / zfont0.c < prev    next >
C/C++ Source or Header  |  1993-05-26  |  7KB  |  222 lines

  1. /* Copyright (C) 1991, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2.  
  3. This file is part of Ghostscript.
  4.  
  5. Ghostscript is distributed in the hope that it will be useful, but
  6. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. to anyone for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.  Refer
  9. to the Ghostscript General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute
  12. Ghostscript, but only under the conditions described in the Ghostscript
  13. General Public License.  A copy of this license is supposed to have been
  14. given to you along with Ghostscript so you can know your rights and
  15. responsibilities.  It should be in a file named COPYING.  Among other
  16. things, the copyright notice and this notice must be preserved on all
  17. copies.  */
  18.  
  19. /* zfont0.c */
  20. /* Composite font creation operator for Ghostscript */
  21. #include "ghost.h"
  22. #include "errors.h"
  23. #include "oper.h"
  24. /*
  25.  * The following lines used to say:
  26.  *    #include "gsmatrix.h"
  27.  *    #include "gxdevice.h"        /. for gxfont.h ./
  28.  * Tony Li says the longer list is necessary to keep the GNU compiler
  29.  * happy, but this is pretty hard to understand....
  30.  */
  31. #include    "gxfixed.h"
  32. #include    "gxmatrix.h"
  33. #include    "gzstate.h"        /* must precede gxdevice */
  34. #include    "gxdevice.h"        /* must precede gxfont */
  35. #include    "gschar.h"
  36. #include "gxfont.h"
  37. #include "alloc.h"
  38. #include "bfont.h"
  39. #include "dict.h"
  40. #include "iname.h"
  41. #include "state.h"
  42. #include "store.h"
  43.  
  44. /* Forward references */
  45. private int ensure_char_entry(P4(os_ptr, const ref *, byte *, int));
  46.  
  47. /* Names of system-known keys in type 0 font dictionaries: */
  48. static ref name_EscChar;
  49. static ref name_FDepVector;
  50. static ref name_FMapType;
  51. static ref name_PrefEnc;
  52. static ref name_ShiftIn;
  53. static ref name_ShiftOut;
  54. static ref name_SubsVector;
  55. static ref name_Type0BuildChar;
  56. static ref name_Type0BuildGlyph;
  57.  
  58. /* Initialize the composite font operators */
  59. private void
  60. zfont0_init(void)
  61. {    static const names_def fnd0[] = {
  62.        { "EscChar", &name_EscChar },
  63.        { "FDepVector", &name_FDepVector },
  64.        { "FMapType", &name_FMapType },
  65.        { "PrefEnc", &name_PrefEnc },
  66.        { "ShiftIn", &name_ShiftIn },
  67.        { "ShiftOut", &name_ShiftOut },
  68.        { "SubsVector", &name_SubsVector },
  69.        { "Type0BuildChar", &name_Type0BuildChar },
  70.        { "Type0BuildGlyph", &name_Type0BuildGlyph },
  71.        names_def_end
  72.     };
  73.     init_names(fnd0);
  74.  
  75.     /* Make the standard BuildChar/BuildGlyph procedures executable. */
  76.     r_set_attrs(&name_Type0BuildChar, a_executable);
  77.     r_set_attrs(&name_Type0BuildGlyph, a_executable);
  78. }
  79.  
  80. /* <string|name> <font_dict> .buildfont0 <string|name> <font> */
  81. /* Build a type 0 (composite) font. */
  82. int
  83. zbuildfont0(os_ptr op)
  84. {    ref *pfmaptype;
  85.     gs_type0_data data;
  86.     ref *pfdepvector;
  87.     ref *pprefenc;
  88.     ref *psubsvector;
  89.     gs_font *pfont;
  90.     font_data *pdata;
  91.     int i;
  92.     int code;
  93.     check_type(*op, t_dictionary);
  94.     if ( dict_find(op, &name_FMapType, &pfmaptype) <= 0 ||
  95.          !r_has_type(pfmaptype, t_integer) ||
  96.          pfmaptype->value.intval < (int)fmap_type_min ||
  97.          pfmaptype->value.intval > (int)fmap_type_max ||
  98.          dict_find(op, &name_FDepVector, &pfdepvector) <= 0 ||
  99.          !r_has_type(pfdepvector, t_array)
  100.        )
  101.         return_error(e_invalidfont);
  102.     data.FMapType = (fmap_type)pfmaptype->value.intval;
  103.     /* Check that every element of the FDepVector is a font. */
  104.     data.fdep_size = r_size(pfdepvector);
  105.     for ( i = 0; i < data.fdep_size; i++ )
  106.        {    ref *pdep = pfdepvector->value.refs + i;
  107.         ref *pfid;
  108.         gs_font *psub;
  109.         if ( !r_has_type(pdep, t_dictionary) ||
  110.              dict_find(pdep, &name_FID, &pfid) <= 0 ||
  111.              !r_has_type(pfid, t_fontID)
  112.            )
  113.             return_error(e_invalidfont);
  114.         /*
  115.          * Check the inheritance rules.  Allowed configurations
  116.          * (paths from root font) are defined by the regular
  117.          * expression:
  118.          *    (shift | double_escape escape* | escape*)
  119.          *      non_modal* non_composite
  120.          */
  121.         psub = pfid->value.pfont;
  122.         if ( psub->FontType == ft_composite )
  123.            {    fmap_type fmt = psub->data.type0_data.FMapType;
  124.             if ( fmt == fmap_double_escape ||
  125.                  fmt == fmap_shift ||
  126.                  fmt == fmap_escape &&
  127.                   !(data.FMapType == fmap_escape ||
  128.                 data.FMapType == fmap_double_escape)
  129.                )
  130.                 return_error(e_invalidfont);
  131.            }
  132.        }
  133.     switch ( data.FMapType )
  134.        {
  135.     case fmap_escape: case fmap_double_escape:    /* need EscChar */
  136.         code = ensure_char_entry(op, &name_EscChar, &data.EscChar, 255);
  137.         break;
  138.     case fmap_shift:            /* need ShiftIn & ShiftOut */
  139.         code = ensure_char_entry(op, &name_ShiftIn, &data.ShiftIn, 15);
  140.         if ( code == 0 )
  141.           code = ensure_char_entry(op, &name_ShiftOut, &data.ShiftOut, 14);
  142.         break;
  143.     case fmap_SubsVector:            /* need SubsVector */
  144.         if ( dict_find(op, &name_SubsVector, &psubsvector) <= 0 ||
  145.              !r_has_type(psubsvector, t_string) ||
  146.              r_size(psubsvector) == 0 ||
  147.              (data.subs_width = (int)*psubsvector->value.bytes + 1) > 4 ||
  148.              (r_size(psubsvector) - 1) % data.subs_width != 0
  149.            )
  150.             return_error(e_invalidfont);
  151.         data.subs_size = (r_size(psubsvector) - 1) / data.subs_width;
  152.         data.SubsVector = psubsvector->value.bytes + 1;
  153.     default:
  154.         code = 0;
  155.        }
  156.     if ( code < 0 ) return code;
  157.     {    static const build_proc_refs build = {
  158.             &name_Type0BuildChar, &name_Type0BuildGlyph
  159.         };
  160.         code = build_gs_font(op, &pfont, ft_composite, &build);
  161.     }
  162.     if ( code != 0 ) return code;
  163.     if ( dict_find(op, &name_PrefEnc, &pprefenc) <= 0 )
  164.        {    ref nul;
  165.         make_null_new(&nul);
  166.         if ( (code = dict_put(op, &name_PrefEnc, &nul)) < 0 )
  167.             return code;
  168.        }
  169.     /* Fill in the font data */
  170.     pdata = (font_data *)(pfont->client_data);
  171.     data.encoding_size = r_size(&pdata->Encoding);
  172.     data.Encoding =
  173.       (uint *)alloc(data.encoding_size, sizeof(uint),
  174.                "buildfont0(Encoding)");
  175.     /* Fill in the encoding vector, checking to make sure that */
  176.     /* each element is an integer between 0 and fdep_size-1. */
  177.     for ( i = 0; i < data.encoding_size; i++ )
  178.        {    ref *penc = pdata->Encoding.value.refs + i;
  179.         if ( !r_has_type(penc, t_integer) ||
  180.              (ulong)penc->value.intval >= data.fdep_size
  181.            )
  182.             return_error(e_invalidfont);
  183.         data.Encoding[i] = (uint)penc->value.intval;
  184.        }
  185.     data.FDepVector =
  186.       (gs_font **)alloc(data.fdep_size, sizeof(gs_font *),
  187.                "buildfont0(FDepVector)");
  188.     for ( i = 0; i < data.fdep_size; i++ )
  189.        {    ref *pfid;
  190.         /* The lookup can't fail, because of the pre-check above. */
  191.         dict_find(pfdepvector->value.refs + i, &name_FID, &pfid);
  192.         data.FDepVector[i] = pfid->value.pfont;
  193.        }
  194.     pfont->data.type0_data = data;
  195.     return define_gs_font(pfont);
  196. }
  197. /* Private routine to find or add an integer entry in a font dictionary. */
  198. private int
  199. ensure_char_entry(os_ptr op, const ref *pname, byte *pvalue, int default_value)
  200. {    ref *pentry;
  201.     if ( dict_find(op, pname, &pentry) <= 0 )
  202.        {    ref ent;
  203.         make_int(&ent, default_value);
  204.         *pvalue = (byte)default_value;
  205.         return dict_put(op, pname, &ent);
  206.        }
  207.     else
  208.       if ( !r_has_type(pentry, t_integer) ||
  209.            (ulong)(pentry->value.intval) > 255
  210.          )
  211.         return_error(e_invalidfont);
  212.     *pvalue = (byte)pentry->value.intval;
  213.     return 0;
  214. }
  215.  
  216. /* ------ Initialization procedure ------ */
  217.  
  218. op_def zfont0_op_defs[] = {
  219.     {"2.buildfont0", zbuildfont0},
  220.     op_def_end(zfont0_init)
  221. };
  222.